

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.rmi.AccessException;
import java.rmi.NotBoundException;
import java.rmi.RemoteException;
import java.rmi.registry.LocateRegistry;
import java.rmi.registry.Registry;
import java.rmi.server.UnicastRemoteObject;
import java.sql.Timestamp;
import java.util.ArrayList;

@SuppressWarnings("serial")
public class ServidorConductor extends UnicastRemoteObject implements IServidorConductor {

	private Registry registry;
	
	private Usuario conductor=null;
	private ArrayList<Usuario> pasajeros= new ArrayList<Usuario>(); // Lista de pasajeros confirmados. con pasajeros.get(i).estaConfirmado=true
	
	
	/*
	 * Inicializa el servidor RMI 
	 */
	public ServidorConductor(String address, int port, Usuario conductor) throws RemoteException{
		super();
		this.conductor = conductor;		
		try{
			registry= LocateRegistry.createRegistry( this.conductor.getPuerto());
			registry.rebind("servidorConductor", this);
		}
		catch(RemoteException e){
			throw e;
		}
	}
	public class Coordina implements Runnable {
		IServidorPasajero companero;
		Registry r;
		int respPasajero = 0;
		Usuario pasajero;
		public Coordina(Usuario p){
			this.pasajero = p ;
		}
		  public void run() {
			  try {
					Registry r=LocateRegistry.getRegistry(pasajero.getIp(), (new Integer(pasajero.getPuerto())).intValue());			
					IServidorPasajero pasajero=(IServidorPasajero)(r.lookup("servidorPasajero"));
					pasajero.coordinarViaje(pasajeros);
				} catch (AccessException e) {
					System.out.println("Error, no tiene acceso para realizar esta accion" );
				} catch (RemoteException e) {
					System.out.println("Error, no es posible contactarse con el pasajero");
				} catch (NotBoundException e) {
					System.out.println("Error, el servidor que se desea buscar no existe");
				}	
		  }
		};
	/*
	 * Enviar solicitud a cada pasajero cercano, si el pasajero acepto, es agregado a la lista pasajeros
	 */
	public void invitarPasajeros(ArrayList<Usuario> pasajeros) throws IOException {
    	IServidorPasajero companero;
		Registry r;
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String resp="";
		int respPasajero = 0;
    	for(int i=0;i<pasajeros.size();i++){
    		if(this.conductor.getNum_asiento()>0){
	    		System.out.print("Desea invitar a "+pasajeros.get(i).getNombre()+" (s/n): ");
				try {
					resp = reader.readLine();
				} catch (IOException e) {
					e.printStackTrace();
				}
				if(resp.compareTo("s")==0){				
					try {
						try{
							System.out.println("Invitando a pasajero");
						    r=LocateRegistry.getRegistry(pasajeros.get(i).getIp(), (new Integer(pasajeros.get(i).getPuerto())).intValue());
						    companero=(IServidorPasajero)(r.lookup("servidorPasajero"));	
						    respPasajero = companero.aceptarConductor(conductor);
						    if(respPasajero==0){
						    	System.out.println("El pasajero rechazo su propuesta");
						    }else if(respPasajero==1){
						    	System.out.println("El pasajero acepto");
						    	this.conductor.setEstado(1);
						    	Usuario u = pasajeros.get(i);
						    	this.pasajeros.add(u);
						    }else{
						    	System.out.println("Error en respuesta");
						    }
						}catch(RemoteException e){
							System.out.println("Error, pasajero incontactable");
						}catch(NotBoundException e){
							e.printStackTrace();
						}
					} catch (NumberFormatException e) {
						e.printStackTrace();
					}	
				}
    		}else{
    			System.out.println("Ya tiene todos los asientos ocupados");
    			break;
    		}
		} 	    	
    }
	
	
	/*
	 * Le envia a cada pasajero, la lista de pasajeros confirmados
	 */
	public void coordinarViaje(){
		//ArrayList<Thread> threads = new ArrayList<Thread>();
		System.out.println("Confirmando el viaje..");
		for (int i = 0; i < pasajeros.size(); i++) {
			
			Coordina c = new Coordina(pasajeros.get(i));
			Thread t = new Thread(c);
			t.start();
		}
	}
    
	@Override
	public int confirmarViaje(Usuario pasajero) throws RemoteException {
		BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
		String resp = null;
		do{
			System.out.print(pasajero.getNombre()+" pregunta si el viaje va (s/n): ");
			try {
				resp = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}
		}while(resp.compareTo("s")!=0 && resp.compareTo("n")!=0);
		
		if(resp.compareTo("s")==0){		
			return 1;			
		}else{
			return 0;
		}
	}   
	
    public ArrayList<Usuario> buscarPasajerosCercanos(float latini, float lonini, float latfin, float lonfin){
    	try {
			return DBManager.getPasajerosCercanos(latini,lonini,latfin,lonfin);
		} catch (NumberFormatException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
		return null;
    }
 
	@Override
	public int cancelarViaje()	throws RemoteException {
		try {
			DBManager.setConductor(conductor.getTelefono(), 0, conductor.getNum_asiento());
			for(int i=0;i<this.pasajeros.size();i++){
				DBManager.setPasajero(pasajeros.get(i).getTelefono(), 0);
				Registry r=LocateRegistry.getRegistry(pasajeros.get(i).getIp(), (new Integer(pasajeros.get(i).getPuerto())).intValue());			
				IServidorPasajero pasajero;
				try {
					pasajero = (IServidorPasajero)(r.lookup("servidorPasajero"));
					pasajero.cancelarViaje(conductor);
				} catch (NotBoundException e) {
					// TODO Auto-generated catch block
					e.printStackTrace();
					return 1;
				}
				
			}
		} catch (IOException e1) {
			// TODO Auto-generated catch block
			e1.printStackTrace();
			return 1;
		}
		
		return 0;
	}

	@Override
	public int reservarAsiento(Usuario usuario, Timestamp time)
			throws RemoteException {
		// TODO Auto-generated method stub
		return 0;
	}

	
}